﻿using Avalonia.Controls;
using LightCAD.Core.Elements;
using LightCAD.Core;
using LightCAD.Runtime;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static LightCAD.Runtime.ElementAction;
using System.Linq.Expressions;
using System.Reflection.Metadata;

namespace LightCAD.Drawing.Action
{
    public class DrawingFrameAction : ElementAction
    {
        private DrawingFrameAction() { }
        public DrawingFrameAction(DocumentRuntime docRt)
         : base(docRt)
        {
            docRt.CommandCtrl.WriteInfo("命令：DrawingFrame");
            this.LcDocument = docRt.Document;
        }
        private static readonly LcCreateMethod[] CreateMethods;
        public LcDocument LcDocument { get; set; }

        static DrawingFrameAction()
        {
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "DrawingFrame",
                Description = "创建图框",
                Steps = new LcCreateStep[]
                                                   {
                                                       new LcCreateStep { Name = "Step0", Options = "指定定位点:" },
                                                       new LcCreateStep { Name = "Step1", Options = "指定定位点或[放弃(U)]:" },
                                                   }
            };
        }
        internal static void Initilize()
        {
            ElementActions.BlockRef = new DrawingFrameAction();
            LcDocument.ElementActions.Add(BuiltinElementType.Drawing, ElementActions.BlockRef);
        }

        private Vector2d? point { get; set; }

        private PointInputer inputer { get; set; }
        private string DrawingName;
        private LcLevel lcLevel;
        private LcBuilding lcBuilding;
        private Vector2d basePoint;
        private Vector2d? firstPoint;
        private List<LcElement> selectedElements = new List<LcElement>();

        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            this.inputer = new PointInputer(this.docRt);
            var curMethod = CreateMethods[0];
            var elementSetInputer = new ElementSetInputer(this.docRt);

            var win = (IFrameDefWindow)AppRuntime.UISystem.CreateWindow("DrawingFrameWindow", this);
            if (this.docRt.Action.SelectedElements.Count > 0)
            {
                win.Elements = new List<LcElement>();
            }
        ShowDlg:
            var result = AppRuntime.UISystem.ShowDialog(win);
            if (result == LcDialogResult.OK)
            {
                //DocumentManager.CurrentRecorder.BeginAction("DrawingFrame");
                if (win.CurrentAction == "SelectPoint")
                {
                    var result1 = await this.inputer.Execute("选择第一个点：");
                    if (result1.Value != null)
                    {
                        firstPoint = (Vector2d)result1.Value;
                        var result2 = await this.inputer.Execute("选择第二个点：");
                        if (result2.Value != null)
                        {
                            Box2d box2D = new Box2d((Vector2d)result1.Value, (Vector2d)result2.Value);
                            win.Box = box2D;
                            basePoint = box2D.Location;
                        }
                    }
                    goto ShowDlg;
                }
                else if (win.CurrentAction == "OK")//
                {
                    this.DrawingName = win.FrameName;
                    this.lcBuilding = win.LcBuilding;
                    this.lcLevel = win.LcLevel;
                    this.CreateOutLine(win);
                    this.CreateDrawing();
                    this.docRt.Action.CancelAll();
                    goto End;
                }
                else if (win.CurrentAction == "Cancel")
                {
                    goto End;
                }
            }
        End:
            this.inputer = null;
            this.EndCreating();

            //DocumentManager.CurrentRecorder.EndAction();
        }
        public void CreateOutLine(IFrameDefWindow win)
        {
            Box2d box2D = (Box2d)win.Box;

            selectedElements.Add(this.vportRt.ActiveElementSet.AddLine(box2D.LeftTop, box2D.RightTop));
            selectedElements.Add(this.vportRt.ActiveElementSet.AddLine(box2D.RightTop, box2D.RightBottom));
            selectedElements.Add(this.vportRt.ActiveElementSet.AddLine(box2D.RightBottom, box2D.LeftBottom));
            selectedElements.Add(this.vportRt.ActiveElementSet.AddLine(box2D.LeftBottom, box2D.LeftTop));
            //增加内框名
            var nameFrameLeftTop = box2D.LeftTop + new Vector2d(0, 300);
            var nameFrameRightTop = box2D.RightTop + new Vector2d(0, 300);
            var nameFrameRightBottom = box2D.RightTop;
            var nameFrameLeftBottom = box2D.LeftTop;
            selectedElements.Add(this.vportRt.ActiveElementSet.AddLine(nameFrameLeftTop, nameFrameRightTop));
            selectedElements.Add(this.vportRt.ActiveElementSet.AddLine(nameFrameRightTop, nameFrameRightBottom));
            selectedElements.Add(this.vportRt.ActiveElementSet.AddLine(nameFrameRightBottom, nameFrameLeftBottom));
            selectedElements.Add(this.vportRt.ActiveElementSet.AddLine(nameFrameLeftBottom, nameFrameLeftTop));
            Text text = new Text();
            text.Value = win.FrameName;
            text.Location = nameFrameLeftBottom + new Vector2d(150, 150);
            this.vportRt.ActiveElementSet.InsertElement(text);
            selectedElements.Add(text);
        }
        public void CreateDrawing()
        {
            var doc = this.docRt.Document;
            var block = doc.CreateObject<LcDrawingFrame>();
            block.Name = this.DrawingName;

            foreach (var element in selectedElements)
            {
                doc.ModelSpace.RemoveElement(element);
                block.InsertElement(element);
            }

            //使用基点，将元素的世界坐标转换为局部坐标
            foreach (var element in selectedElements)
            {
                element.Translate(-basePoint);
            }

            //转换完成后，将基点的局部坐标设置为零零
            //block.BasePoint = Vector2d.Zero;
            doc.Blocks.Add(block);//TODO 需要触发事件

            var blockRef = doc.CreateObject<LcDrawing>(block);
            blockRef.Name = this.DrawingName;
            blockRef.Set(matrix: Matrix3d.Translate(basePoint));
            this.lcLevel.Drawings.Add(blockRef);
            doc.ModelSpace.InsertElement(blockRef);
        }


        public override void Draw(SKCanvas canvas, LcElement element, Matrix3d matrix)
        {
            var blockRef = element as LcDrawing;
            RefStack.Push(blockRef);
            try
            {
                var mat = matrix * blockRef.Matrix;
                List<Text> texts = new List<Text>();
                foreach (var ele in blockRef.Block.Elements)
                {
                    if (ele is Text)
                    {
                        texts.Add((Text)ele);
                        continue;
                    }
                    var eleAction = (ele.RtAction as ElementAction);

                    eleAction.SetViewport(this.vportRt).Draw(canvas, ele, mat);

                }
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {
                    foreach (var item in texts)
                    {
                        var location = this.vportRt.ConvertWcsToScr(item.Location);
                        canvas.DrawText(item.Value, (float)location.X, (float)location.Y, elePen);

                    }
                }
            }
            catch (Exception ex)
            {
            }
            finally
            {
                RefStack.Pop();
            }

            if (matrix == Matrix3d.Identity)
            {
                var leftTop = this.vportRt.ConvertWcsToScr(blockRef.BoundingBox.LeftTop);
                var rightBottom = this.vportRt.ConvertWcsToScr(blockRef.BoundingBox.RightBottom);
                canvas.DrawRect((float)leftTop.X, (float)leftTop.Y, (float)rightBottom.X - (float)leftTop.X, (float)rightBottom.Y - (float)leftTop.Y, Constants.SilverPen);
            }
        }

        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var lcDrawing = element as LcDrawing; //getHel
            var grips = new List<ControlGrip>();
            //var box = lcDrawing.BoundingBox;
            //var LeftTopPoint = new ControlGrip
            //{
            //    Element = lcDrawing,
            //    Name = "LeftTop",
            //    Position = box.LeftTop
            //};
            //grips.Add(LeftTopPoint);
            //var LeftBottomPoint = new ControlGrip
            //{
            //    Element = lcDrawing,
            //    Name = "LeftBottom",
            //    Position = box.LeftBottom
            //};
            //grips.Add(LeftBottomPoint);
            //var RightTopPoint = new ControlGrip
            //{
            //    Element = lcDrawing,
            //    Name = "RightTop",
            //    Position = box.RightTop
            //};
            //grips.Add(RightTopPoint);
            //var RightBottomPoint = new ControlGrip
            //{
            //    Element = lcDrawing,
            //    Name = "RightBottom",
            //    Position = box.RightBottom
            //};
            //grips.Add(RightBottomPoint);

            var insertPoint = new ControlGrip
            {
                Element = lcDrawing,
                Name = "InsertPoint",
                Position = lcDrawing.Matrix.GetTranslateVector()
            };
            grips.Add(insertPoint);
            return grips.ToArray();
        }
        private string _gripName;

        private Vector2d _position;
        private LcDrawing _basePoint;

        public override void SetDragGrip(LcElement element, string gripName, Vector2d position, bool isEnd)
        {

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="canvas"></param>
        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_basePoint == null) return;

        }
        public override void DrawAuxLines(SKCanvas canvas)
        {
            if (firstPoint == null) return;
            var mp = this.vportRt.PointerMovedPosition.ToVector2d();
            var wcs_mp = this.vportRt.ConvertScrToWcs(mp);

            Vector2d anglePoint1 = (Vector2d)firstPoint;
            Vector2d anglePoint3 = wcs_mp;
            Vector2d anglePoint2 = new Vector2d(anglePoint1.X, anglePoint3.Y);
            Vector2d anglePoint4 = new Vector2d(anglePoint3.X, anglePoint1.Y);

            var SKPoint1 = this.vportRt.ConvertWcsToScr(anglePoint1).ToSKPoint();
            var SKPoint2 = this.vportRt.ConvertWcsToScr(anglePoint2).ToSKPoint();
            var SKPoint3 = this.vportRt.ConvertWcsToScr(anglePoint3).ToSKPoint();
            var SKPoint4 = this.vportRt.ConvertWcsToScr(anglePoint4).ToSKPoint();
            //辅助元素的颜色 
            canvas.DrawLine(SKPoint1, SKPoint2, Constants.auxElementPen);
            canvas.DrawLine(SKPoint2, SKPoint3, Constants.auxElementPen);
            canvas.DrawLine(SKPoint3, SKPoint4, Constants.auxElementPen);
            canvas.DrawLine(SKPoint4, SKPoint1, Constants.auxElementPen);
        }

    }
}
